package br.edu.ufcg.embedded.util.algo;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;

import br.edu.ufcg.embedded.domain.CustomVertex;
import br.edu.ufcg.embedded.domain.DirectedGraphBuilder;
import br.embedded.socialapp.data.FriendshipDAO;

public class GraphGenerator2 {
	
	private DirectedGraphBuilder graphBuilder;
	private Hashtable<String, Integer> internalCounters;
	private Hashtable<String, Float> calculated, target;
	
	public GraphGenerator2(Hashtable<String, Float> matrix) {
		
		this.graphBuilder = new DirectedGraphBuilder();
		this.target = matrix;
		initialize();
	}
	
	public Graph<String, DefaultEdge> generate(int sampleSize) {

		Queue<CustomVertex> queue = new LinkedList<CustomVertex>();
		CustomVertex root = FriendshipDAO.getInstance().getRandomVertices("B", 1).get(0);

		List<CustomVertex> list = FriendshipDAO.getInstance().getFollowing(root);

		for (CustomVertex customVertex : list) {
			queue.add(customVertex);
		}

		list = null;

		graphBuilder.add(root.toString());
		internalCounters.put(root.getClassification(), internalCounters.get(root.getClassification()) + 1);

		while (!queue.isEmpty()) {

			CustomVertex vertex = queue.remove();

			if (graphBuilder.add(vertex.toString())) {

				int tmpCount = internalCounters.get(vertex.getClassification());
				internalCounters.put(vertex.getClassification(), tmpCount + 1);
				calculate();
			}

			graphBuilder.addEdge(vertex.getParent(), vertex.toString());

			if (!checkCounters(sampleSize)) {

				List<CustomVertex> n2 = FriendshipDAO.getInstance().getFollowing(vertex);

				for (CustomVertex v : n2) {
					queue.add(v);
				}
			}
			else //if (graphBuilder.getVerticesSize() >= sampleSize)
				break;

			System.out.println(calculated);
			//System.out.println(counters);
		}

		//if (graphBuilder.getVerticesSize() >= sampleSize)
		


		/*list = FriendshipDAO.getInstance().getRandomVertices("A", counters.get("A"));
		int count = counters.get("A"); 

		for (CustomVertex v : list) 
		{
			if (graphBuilder.add(v.toString()))
				count--;
		}
		counters.put("A", count);*/
		//calculate();
		System.out.println("Inicial >>> " + target);
		System.out.println("Final >>> " + calculated);
		System.out.println(internalCounters);

		return graphBuilder.getGraph();
	}
	
	private void calculate() {
		
		Iterator<String> it = internalCounters.keySet().iterator();
		int total = graphBuilder.getVerticesSize();
		
		while (it.hasNext()) {
			
			String key = it.next();
			float result = ((float) (internalCounters.get(key) * 1.000000000) / total);
			calculated.put(key, result);	
		}
	}
	
	private boolean checkCounters(int sampleSize) {
		
		Iterator<String> it = calculated.keySet().iterator();
		int total = graphBuilder.getVerticesSize();
		
		while (it.hasNext()) {
			
			String key = it.next();
			
			if ((calculated.get(key) >= target.get(key)) && total >= sampleSize)
				continue;
			else
				return false;
			
			
			
		}
		
		return true;
	}
	
	private void initialize()
	{
		this.internalCounters = new Hashtable<String, Integer>();
		this.calculated = new Hashtable<String, Float>();
		
		for (String key : target.keySet()) {
			
			this.internalCounters.put(key, new Integer(0));
			this.calculated.put(key, new Float(0.0));
		}
	}
}